package com.gjs.common.manager;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.gjs.common.manager.notification.INotification;
import com.gjs.common.manager.notification.sms.SmsMessage;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.concurrent.TimeUnit;

@Component
@Data
public class SmsVerifyCode {

    @Autowired
    private INotification notification;

    @Autowired
    private RedisOperations<String, Object> redisUtil;

    private String registerCacheKey;

    private Long registerExpire;

    private String loginCacheKey;

    private Long loginExpire;

    private String restPasswordCacheKey;

    private Long restPasswordExpire;

    public enum VerifyType {
        LOGIN, REGISTER, RESET_PASSWORD
    }

    /**
     * 发送验证码短信
     *
     * @param verifyType VerifyType 验证码类型
     * @param mobile     String 手机号
     */
    public boolean send(VerifyType verifyType, String mobile) {
        String cacheKey = null;
        Long expire = 0L;
        String validCode = "";

        // 通过策略模式区分要发送的验证码类型及业务参数
        switch (verifyType) {
            case LOGIN:
                cacheKey = loginCacheKey;
                expire = loginExpire;
                validCode = String.valueOf(RandomUtil.randomInt(1000, 9999));
                break;
            case REGISTER:
                cacheKey = registerCacheKey;
                expire = registerExpire;
                validCode = String.valueOf(RandomUtil.randomInt(100000, 999999));
                break;
            case RESET_PASSWORD:
                cacheKey = restPasswordCacheKey;
                expire = restPasswordExpire;
                validCode = String.valueOf(RandomUtil.randomInt(100000, 999999));
                break;
        }
        // 构造短信信息体
        String paramJsonStr = JSONUtil.toJsonStr(MapUtil.of("code", validCode));
        SmsMessage smsMessage = new SmsMessage();
        smsMessage.setAliyunSignName("广东教育出版社");
        smsMessage.setTemplateCode("SMS_225995175");
        smsMessage.setTarget(mobile);
        smsMessage.setContent(paramJsonStr);

        String cacheFullKey = cacheKey + smsMessage.getTarget();
        // 校验手机号
        Validator.validateMobile(smsMessage.getTarget(), "无效手机号");
        // 检查是否已经发送过了
        String check = (String) redisUtil.opsForValue().get(cacheFullKey);
        Assert.isNull(check, "短信已发送，请勿重复操作");
        // 执行短信发送
        notification.send(smsMessage);
        // 保存到redis中，防止恶意刷
        redisUtil.opsForValue().set(cacheFullKey, validCode, expire, TimeUnit.SECONDS);
        // 没报错就代表成功了咯
        return true;
    }

    /**
     * 校验短信验证码
     *
     * @param verifyType VerifyType 验证码类型
     * @param mobile     String 手机号
     * @param code       String 验证码
     */
    public boolean verify(VerifyType verifyType, String mobile, String code) {
        String cacheKey = "";
        switch (verifyType) {
            case LOGIN:
                cacheKey = loginCacheKey;
                break;
            case REGISTER:
                cacheKey = registerCacheKey;
                break;
            case RESET_PASSWORD:
                cacheKey = restPasswordCacheKey;
                break;
        }

        Object redisValidCode = redisUtil.opsForValue().get(cacheKey + mobile);
        if (redisValidCode == null) {
            return false;
        }

        return String.valueOf(redisValidCode).equals(code);
    }
}
